/**
 * This file is released under the GNU General Public License.
 * Refer to the COPYING file distributed with this package.
 *
 * Copyright (c) 2008-2009 WURFL-Pro srl
 */
package net.sourceforge.wurfl.core.resource;

import java.util.List;
import java.util.Set;

import net.sourceforge.wurfl.core.CapabilityNotDefinedException;
import net.sourceforge.wurfl.core.DeviceNotDefinedException;
import net.sourceforge.wurfl.core.GroupNotDefinedException;

/**
 * <p>
 * This interface is used to access to the {@link ModelDevice}s. The class need
 * access to the {@link ModelDevice}s, must to use this interface.
 * </p>
 * 
 * <p>
 * The main aim of this interface is to hold the object model of WURFL
 * repository, the implementing classes can held the {@link ModelDevice}s
 * instance in several different manner.
 * </p>
 * 
 * @author WURFL-PRO SRL, Rome, Italy
 * @version $Id: WURFLModel.java 1045 2009-03-09 15:52:53Z filippo.deluca $
 */
public interface WURFLModel {

	/**
	 * Returns the version info of wurfl repository.
	 * 
	 * <p>
	 * The returning string may vary by the kind of resources used to build
	 * model.
	 * </p>
	 * 
	 * @return String represents wurfl repository version.
	 */
	public String getVersion();

	/**
	 * Returns {@link ModelDevice} by his id.
	 * 
	 * @param id
	 *            The identifier of requested device
	 * @return ModelDevice identified by id.
	 * @throws DeviceNotDefinedException
	 *             If this model do not manage the device with given id.
	 */
	public ModelDevice getDeviceById(String id)
			throws DeviceNotDefinedException;

	/**
	 * Return if this model define ModelDevice with given id.
	 * 
	 * @param id
	 *            The identifier to probe.
	 * @return True if the device is defined, false otherwise.
	 */
	public boolean isDeviceDefined(String id);

	/**
	 * Return all defined devices.
	 * 
	 * @return Set of {@link ModelDevice}
	 */
	public Set/* ModelDevice */getAllDevices();

	/**
	 * Return all defined devices identifiers.
	 * 
	 * @return Set of string representing the devices identifier.
	 */
	public Set/* String */getAllDevicesId();

	/**
	 * Return the devices with given identifiers.
	 * 
	 * @param ids
	 *            The identifiers of the devices to retrieve.
	 * @return Set of {@link ModelDevice}
	 * @throws DeviceNotDefinedException
	 *             If a device with the passed identifier is not defined in this
	 *             model.
	 */
	public Set/* ModelDevice */getDevices(Set/* String */ids)
			throws DeviceNotDefinedException;

	/**
	 * Returns device hierarchy.
	 * 
	 * <p>
	 * A hierarchy is a ordered list of {@link ModelDevice} instances, starting
	 * <strong>form <code>generic</code> to <code>device</code></strong>. <br />
	 * 
	 * <pre>
	 *  Generic -&gt; ... -&gt; device
	 * </pre>
	 * 
	 * </p>
	 * 
	 * @param root
	 *            The device to get hierarchy.
	 * @return A {@link List} of {@link ModelDevice} representing the device's
	 *         hierarchy.
	 */
	public List/* ModelDevice */getDeviceHierarchy(ModelDevice root)
			throws DeviceNotInModelException;

	/**
	 * Return the device's fallback.
	 * 
	 * @param target
	 *            The device to get fallback.
	 * @return A ModelDevice fallback of given <code>device</code>.
	 * @throws DeviceNotInModelException
	 *             If the given <code>device</code> is not held by this model.
	 */
	public ModelDevice getDeviceFallback(ModelDevice target)
			throws DeviceNotInModelException;

	/**
	 * Return a {@link ModelDevice} ancestor.
	 * 
	 * <p>
	 * The ancestor is the first root device found iterating over the
	 * <code>device</code> hierarchy, from root to generic.
	 * </p>
	 * 
	 * @param target
	 *            The device from get the ancestor.
	 * @return The root target device parent.
	 */
	public ModelDevice getDeviceAncestor(ModelDevice target)
			throws DeviceNotInModelException;

	/**
	 * Return the size (number of held devices) of this model.
	 * 
	 * @return The size of this model.
	 */
	public int size();

	// Capabilities *******************************************************

	/**
	 * Return all capabilities name defined by held {@link ModelDevice}s.
	 * 
	 * @return A Set of String containing the capabilities name.
	 */
	public Set/* String */getAllCapabilities();

	/**
	 * Return if a capability is defined by the held {@link ModelDevice}s.
	 * 
	 * @param capability
	 *            The capability to probe.
	 * @return true if the capability is defined, false otherwise.
	 */
	public boolean isCapabilityDefined(String capability);

	/**
	 * Return the group in which a capability is defined.
	 * 
	 * @param capability
	 *            The capability to find group for.
	 * @return The capability parent group identifier.
	 * @throws CapabilityNotDefinedException
	 *             If the given capability is not defined by this model.
	 */
	public String getGroupByCapability(String capability)
			throws CapabilityNotDefinedException;

	/**
	 * Return a {@link ModelDevice}, found iterating a {@link ModelDevice}
	 * hierarchy, defining the given capability.
	 * 
	 * @param root
	 *            The devices to iterate from.
	 * @param capability
	 *            The capability to probe.
	 * @return The {@link ModelDevice} defining given capability.
	 * @throws DeviceNotInModelException
	 *             If the device is not held by this model.
	 * @throws CapabilityNotDefinedException
	 *             If the capability to probe is not defined by this model.
	 */
	public ModelDevice getDeviceWhereCapabilityIsDefined(ModelDevice root,
			String capability) throws DeviceNotInModelException,
			CapabilityNotDefinedException;

	// Groups *************************************************************

	/**
	 * Return all defined group's identifiers.
	 */
	public Set/* String */getAllGroups();

	/**
	 * Return if a group is defined by this model.
	 * 
	 * @param groupId
	 *            The group to probe.
	 * @return true if the held {@link ModelDevice}s definig the given group.
	 */
	public boolean isGroupDefined(String groupId);

	/**
	 * Return the capabilities defined in the given group.
	 * 
	 * @param group
	 *            The identifier of group to get capabilities from.
	 * @return A Set of capabilities identifiers.
	 * @throws GroupNotDefinedException
	 *             If the given group is not defined by the held
	 *             {@link ModelDevice}s.
	 */
	public Set/* String */getCapabilitiesForGroup(final String group)
			throws GroupNotDefinedException;

}
